package com.zhuguowei.rxjavademo;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;


public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    @BindView(R.id.btn_sync)
    Button mBtnSync;
    @BindView(R.id.btn_async)
    Button mBtnAsync;
    @BindView(R.id.iv_icon)
    ImageButton mIvIcon;
    @BindView(R.id.btn_flatMap)
    Button mBtnFlatMap;
    @BindView(R.id.tv_student)
    TextView mTvStudent;
    @BindView(R.id.tv_course)
    TextView mTvCourse;
    private int mDrawableRes;
    private boolean isClick;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        mDrawableRes = R.mipmap.icon_xkzb;
    }


    //在不指定线程的情况下， RxJava 遵循的是线程不变的原则，即：
    // 在哪个线程调用 subscribe()，就在哪个线程生产事件；
    // 在哪个线程生产事件，就在哪个线程消费事件。
    // 如果需要切换线程，就需要用到 Scheduler （调度器）。 zgw-2018/3/24 14:39
    /* Schedulers.immediate(): 直接在当前线程运行，相当于不指定线程。这是默认的 Scheduler。
     * Schedulers.newThread(): 总是启用新线程，并在新线程执行操作。
     * Schedulers.io(): I/O 操作（读写文件、读写数据库、网络信息交互等）所使用的 Scheduler。行为模式和 newThread() 差不多，
     * 区别在于 io() 的内部实现是是用一个无数量上限的线程池，可以重用空闲的线程，因此多数情况下 io() 比 newThread() 更有效率。
     * 不要把计算工作放在 io() 中，可以避免创建不必要的线程。
     * Schedulers.computation(): 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算，即不会被 I/O 等操作限制性能的操作，例如图形的计算。
     * 这个 Scheduler 使用的固定的线程池，大小为 CPU 核数。不要把 I/O 操作放在 computation() 中，否则 I/O 操作的等待时间会浪费 CPU。
     * 另外， Android 还有一个专用的 AndroidSchedulers.mainThread()，它指定的操作将在 Android 主线程运行。
     * 有了这几个 Scheduler ，就可以使用 subscribeOn() 和 observeOn() 两个方法来对线程进行控制了。
     * subscribeOn(): 指定 subscribe() 所发生的线程，即 Observable.OnSubscribe 被激活时所处的线程。或者叫做事件产生的线程。
     * observeOn(): 指定 Subscriber 所运行在的线程。或者叫做事件消费的线程。
     */
    private void changeImageScheduler() {
        Observable.create(new ObservableOnSubscribe<Drawable>() {

            @Override
            public void subscribe(ObservableEmitter<Drawable> emitter) throws Exception {
                Drawable drawable = getResources().getDrawable(mDrawableRes);
                emitter.onNext(drawable);
                emitter.onComplete();
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Drawable>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "onSubscribe: ");
            }

            @Override
            public void onNext(Drawable drawable) {
                mIvIcon.setImageDrawable(drawable);
            }

            @Override
            public void onError(Throwable e) {
                Toast.makeText(MainActivity.this, "error", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete: ");
            }
        });
    }

    //线程同步执行 zgw-2018/3/24 14:38
    private void changeImage() {
        Observable.create(new ObservableOnSubscribe<Drawable>() {

            @Override
            public void subscribe(ObservableEmitter<Drawable> emitter) throws Exception {
                Drawable drawable = getResources().getDrawable(mDrawableRes);
                emitter.onNext(drawable);
                emitter.onComplete();
            }
        }).subscribe(new Observer<Drawable>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "onSubscribe: ");
            }

            @Override
            public void onNext(Drawable drawable) {
                mIvIcon.setImageDrawable(drawable);
            }

            @Override
            public void onError(Throwable e) {
                Toast.makeText(MainActivity.this, "error", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete: ");
            }
        });
    }

    @OnClick({R.id.btn_sync, R.id.btn_async, R.id.btn_flatMap})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.btn_sync:
                mDrawableRes = isClick == false ? R.mipmap.icon_xkzb : R.mipmap.ic_launcher;
                changeImage();
                isClick = !isClick;
                break;
            case R.id.btn_async:
                mDrawableRes = isClick == false ? R.mipmap.icon_xkzb : R.mipmap.ic_launcher;
                changeImageScheduler();
                isClick = !isClick;
                break;
            case R.id.btn_flatMap:
                flatMap();
                break;
        }
    }

    private void flatMap() {
        List<Course> courseList1 = new ArrayList<>();
        courseList1.add(new Course("张三-语文"));
        courseList1.add(new Course("张三-数学"));
        courseList1.add(new Course("张三-英语"));
        courseList1.add(new Course("张三-政治"));
        courseList1.add(new Course("张三-历史"));
        Student student1 = new Student("张三", courseList1);
        List<Course> courseList2 = new ArrayList<>();
        courseList2.add(new Course("李四-语文"));
        courseList2.add(new Course("李四-数学"));
        courseList2.add(new Course("李四-英语"));
        courseList2.add(new Course("李四-政治"));
        courseList2.add(new Course("李四-历史"));
        Student student2 = new Student("李四", courseList2);
        List<Course> courseList3 = new ArrayList<>();
        courseList3.add(new Course("王五-语文"));
        courseList3.add(new Course("王五-数学"));
        courseList3.add(new Course("王五-英语"));
        courseList3.add(new Course("王五-政治"));
        courseList3.add(new Course("王五-历史"));
        Student student3 = new Student("王五", courseList3);
        List<Course> courseList4 = new ArrayList<>();
        courseList4.add(new Course("赵六-语文"));
        courseList4.add(new Course("赵六-数学"));
        courseList4.add(new Course("赵六-英语"));
        courseList4.add(new Course("赵六-政治"));
        courseList4.add(new Course("赵六-历史"));
        Student student4 = new Student("赵六", courseList4);
        Student[] students = {student1, student2, student3, student4};
        Consumer<Course> consumer = new Consumer<Course>() {
            @Override
            public void accept(Course course) throws Exception {
                Log.e(TAG, "accept: course : " + course.getName());
//                Toast.makeText(MainActivity.this, "course：" + course.getName(), Toast.LENGTH_SHORT).show();
                mTvCourse.setText(course.getName());
                Thread.sleep(100);
            }
        };
        Observable.fromArray(students)
                .flatMap(new Function<Student, ObservableSource<Course>>() {
                    @Override
                    public ObservableSource<Course> apply(Student student) throws Exception {
                        Log.e(TAG, "apply: ================student:" + student.getName() + "================");
//                        Toast.makeText(MainActivity.this, "student：" + student.getName(), Toast.LENGTH_SHORT).show();
//                        mTvStudent.setText(student.getName());
//                        Thread.sleep(4000);
                        return Observable.fromIterable(student.getCourse());
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(consumer);
    }

}
